﻿using FirstFloor.ModernUI.Windows;
using FirstFloor.ModernUI.Windows.Controls;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using TanmiaGrp.Basis;

namespace TanmiaGrp.GeneralLedger.WinApp.Scenarios
{
    /// <summary>
    /// Interaction logic for JournalEditorView.xaml
    /// </summary>
    public partial class JournalEditorView : UserControl, IContent
    {
        private static JournalEditorViewModel viewModel;

        public JournalEditorView()
        {
            InitializeComponent();

            if (viewModel == null)
                viewModel = new JournalEditorViewModel { Close = CloseView };

            DataContext = viewModel;
        }


        /// <summary>
        /// Called when Pop-out button is pressed, to popup the window from the docked workspace.
        /// </summary>
        private void OnPopout(object sender, RoutedEventArgs e)
        {
            // Create new EditorView and assign the same EditorViewModel object to it.
            // Hide the popup button because no need to popup an already popuped EditorView.
            JournalEditorView popupEditorView = new JournalEditorView();
            popupEditorView.windowBar.PopoutVisibility = System.Windows.Visibility.Collapsed;

            // Create and show the popuped window.
            FloatWindow popoutWindow = new FloatWindow
            {
                Content = popupEditorView,
                ShowActivated = true,
                Owner = Application.Current.MainWindow
            };

            popoutWindow.Show();

            // Notify MainWindowViewModel to keep track for new popoutWindow.
            Events.FloatWindowShown.Fire(popoutWindow);
        }

        #region IContent Members

        public void OnFragmentNavigation(FirstFloor.ModernUI.Windows.Navigation.FragmentNavigationEventArgs e) { }

        public void OnNavigatedFrom(FirstFloor.ModernUI.Windows.Navigation.NavigationEventArgs e) { }

        /// <summary>
        /// Called when current view is got the navigation.
        /// </summary>
        /// <param name="e"></param>
        public void OnNavigatedTo(FirstFloor.ModernUI.Windows.Navigation.NavigationEventArgs e)
        {
            TanmiaGrp.GeneralLedger.Core.Journal entity = null;

            // When BaseBrowserViewModel request to edit BusinessObject, TryReceive method will return true.
            // entity BusinessObject will be null if BaseBrowserViewModel request to add new BusinessObject.
            Events.UpdateCurrentView.TryReceive<TanmiaGrp.GeneralLedger.Core.Journal>(out entity);

            viewModel.Entity = entity;
        }

        public void OnNavigatingFrom(FirstFloor.ModernUI.Windows.Navigation.NavigatingCancelEventArgs e) { }

        #endregion

        /// <summary>
        /// Close the View that contains current EditorView.
        /// Because one ViewModel object may control many EditorViewModel objects, we have to determine where 
        /// current EditorView is contained to close it accordingly.
        /// </summary>
        /// <param name="sender">Represents the button that send Close view.</param>
        public void CloseView(object sender)
        {
            FrameworkElement senderElm = sender as FrameworkElement;

            // check if JournalEditorView is contained within FloatWindow
            FloatWindow floatWindow = senderElm.TryGetParent<FloatWindow>();
            if (floatWindow != null)
                floatWindow.Close();

            // otherwise if JournalEditorView is contained within ModernFrame that mean it is docked.
            ModernFrame modernFrame = senderElm.TryGetParent<ModernFrame>();
            if (modernFrame != null)
                modernFrame.Source = null;
        }

        private void OnKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                // when no select row, we get the row the have selected cell.
                DataGridRow selectedRow = dgEntries.GetSelectedRow() ?? dgEntries.GetCurrentRow();

                // select the row if it is not selected
                if (selectedRow != null && !selectedRow.IsSelected)
                    selectedRow.Focus();

                // if we couldn't get or select row, exit.
                if (selectedRow == null)
                    return;

                // get current cell
                int colIndex = dgEntries.Columns.IndexOf(dgEntries.CurrentColumn);
                DataGridCell currentCell = dgEntries.GetCell(selectedRow, colIndex);

                // when entering to the last column.
                if (dgEntries.CurrentCell.Column.DisplayIndex == dgEntries.Columns.Count - 1)
                {
                    if (currentCell.IsEditing)
                    {
                        dgEntries.CommitEdit();
                    }
                    else
                    {
                        PressKey(Key.Return);

                        // get the new row and move focus to the first cell.
                        DataGridRow newRow = dgEntries.GetSelectedRow();
                        newRow = (DataGridRow)dgEntries.ItemContainerGenerator.ContainerFromItem(dgEntries.CurrentItem);
                        newRow.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));

                        dgEntries.BeginEdit();
                    }
                }
                else
                {
                    if (currentCell.IsEditing)
                    {
                        dgEntries.CommitEdit();

                        currentCell.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next) { Wrapped = true });
                    }

                    dgEntries.BeginEdit();
                }

                dgEntries.SelectedItem = dgEntries.CurrentItem;
                e.Handled = true;
                dgEntries.UpdateLayout();
            }
        }

        private void PressKey(Key key)
        {
            KeyEventArgs args = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, key);
            args.RoutedEvent = Keyboard.KeyDownEvent;
            InputManager.Current.ProcessInput(args);
        }

        private void dgEntries_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
        {
            //if (e.AddedCells.Count == 0) return;
            //var currentCell = e.AddedCells[0];
            //string header = (string)currentCell.Column.Header;

            //if (currentCell.Column == dgEntries.Columns[2])
            //{
            //    int colIndex = currentCell.Column.DisplayIndex;
            //    int rowIndex = dgEntries.GetCurrentRow().GetIndex();
            //    DataGridCell cell = dgEntries.GetCell(rowIndex, colIndex);
            //    ContentPresenter cp = cell.Content as ContentPresenter;
            //    ComboBox cb = cp.ContentTemplate.FindName("taskCombo", cp) as ComboBox;
            //    cb.Focus();

            //    dgEntries.BeginEdit();
            //}

        }

        private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DataGridCell cell = sender as DataGridCell;
            if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
            {
                if (!cell.IsFocused)
                {
                    cell.Focus();
                }
                DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
                if (dataGrid != null)
                {
                    if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
                    {
                        if (!cell.IsSelected)
                            cell.IsSelected = true;
                    }
                    else
                    {
                        DataGridRow row = FindVisualParent<DataGridRow>(cell);
                        if (row != null && !row.IsSelected)
                        {
                            row.IsSelected = true;
                        }
                    }
                }
            }
        }

        static T FindVisualParent<T>(UIElement element) where T : UIElement
        {
            UIElement parent = element;
            while (parent != null)
            {
                T correctlyTyped = parent as T;
                if (correctlyTyped != null)
                {
                    return correctlyTyped;
                }

                parent = VisualTreeHelper.GetParent(parent) as UIElement;
            }
            return null;
        }

        public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
        {
            if (depObj != null)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                    if (child != null && child is T)
                    {
                        yield return (T)child;
                    }

                    foreach (T childOfChild in FindVisualChildren<T>(child))
                    {
                        yield return childOfChild;
                    }
                }
            }
        }
        private void dgEntries_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
        {
            UIElement inputElement;
            ///
            /// Texbox is the first control in my template column
            ///
            inputElement = FindVisualChildren<ComboBox>(e.EditingElement).FirstOrDefault();// dgEntries.GetVisualChild<TextBox>(e.EditingElement);
            if (inputElement != null)
            {
                Keyboard.Focus(inputElement);
            }
        }

        private void taskCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }

        private void taskCombo_KeyDown(object sender, KeyEventArgs e)
        {
            Debug.WriteLine(e.Key);
        }
    }
}
